package com.lh.java.basic.threadlocal;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 ************************************************
 ** Module : 模拟单个线程对多个线程的唤醒
模拟线程之间的协作。Game类有2个同步方法prepare()和go()。
标志位start用于判断当前线程是否需要wait()。
Game类的实例首先启动所有的Athele类实例，使其进入wait()状态，
在一段时间后，改变标志位并notifyAll()所有处于wait状态的Athele线程。
 ** Date: 2013-3-29  Time: 下午03:06:02 
 ** Author lh 
 ************************************************ 
 */
class Athlete implements Runnable {
	private final int id;
	private Game game;

	public Athlete(int id, Game game) {
		this.id = id;
		this.game = game;
	}

	public boolean equals(Object o) {
		if (!(o instanceof Athlete))
			return false;
		Athlete athlete = (Athlete) o;
		return id == athlete.id;
	}

	public String toString() {
		return "Athlete<" + id + ">";
	}

	public int hashCode() {
		return new Integer(id).hashCode();
	}

	public void run() {
		try {
			game.prepare(this);
		} catch (InterruptedException e) {
			System.out.println(this + " quit the game");
		}
	}
}

public class Game implements Runnable {
	private Set<Athlete> players = new HashSet<Athlete>();
	private boolean start = false;

	public void addPlayer(Athlete one) {
		players.add(one);
	}

	public void removePlayer(Athlete one) {
		players.remove(one);
	}

	public Collection<Athlete> getPlayers() {
		return Collections.unmodifiableSet(players);
	}

	public void prepare(Athlete athlete) throws InterruptedException {
		System.out.println(athlete + " ready!");
		synchronized (this) {
			while (!start)
				wait();
			if (start)
				System.out.println(athlete + " go!");
		}
	}

	public synchronized void go() {
		notifyAll();
	}

	public void ready() {
		Iterator<Athlete> iter = getPlayers().iterator();
		while (iter.hasNext())
			new Thread(iter.next()).start();
	}

	public void run() {
		start = false;
		System.out.println("Ready......");
		System.out.println("Ready......");
		System.out.println("Ready......");
		ready();
		start = true;
		System.out.println("Go!");
		go();
	}

	public static void main(String[] args) {
		Game game = new Game();
		for (int i = 0; i < 10; i++)
			game.addPlayer(new Athlete(i, game));
		new Thread(game).start();
	}
}
